#include "../global.h"

class vtkTIPWCallback : public vtkCommand
{
public:
    static vtkTIPWCallback *New()
    {
        return new vtkTIPWCallback;
    }

    virtual void Execute(vtkObject *caller, unsigned long, void*)
    {
        vtkImplicitPlaneWidget *planeWidget = reinterpret_cast<vtkImplicitPlaneWidget*>(caller);
        planeWidget->GetPlane(m_plane);
        m_vMapper->AddClippingPlane(m_plane);
        m_volume->VisibilityOn();
    }

    void setParameter(vtkPlane *p, vtkVolume *v, vtkVolumeRayCastMapper *m)
    {
        m_plane = p;
        m_volume = v;
        m_vMapper = m;
    }
protected:
    vtkTIPWCallback():m_plane(0),m_volume(0),m_vMapper(0){}
    vtkPlane *m_plane;
    vtkVolume *m_volume;
    vtkVolumeRayCastMapper *m_vMapper;

};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    vtkCreate(reader, vtkDICOMImageReader);
    reader->SetDataByteOrderToLittleEndian();
    reader->SetDirectoryName(path.toStdString().c_str());
    reader->Update();

    vtkCreate(renderer, vtkRenderer);
    vtkWidgetCreate(widget, QVTKWidget);
    QVTKWidget* vtkWidget = widget.data();
    vtkWidget->GetRenderWindow()->AddRenderer(renderer);

    vtkCreate(imageCast, vtkImageCast);
    imageCast->SetInputConnection(reader->GetOutputPort());
    imageCast->SetOutputScalarTypeToUnsignedShort();
    imageCast->Update();

    vtkCreate(opacityTransferFunction, vtkPiecewiseFunction);
    opacityTransferFunction->AddPoint(20, 0.0);
    opacityTransferFunction->AddPoint(255.0, 0.22);

    vtkCreate(colorTransferFunction, vtkColorTransferFunction);
    colorTransferFunction->AddRGBPoint(0.0, 0.0, 0.5, 0.0);
    colorTransferFunction->AddRGBPoint(60.0, 1.0, 0.0, 0.0);
    colorTransferFunction->AddRGBPoint(128.0, 0.2, 0.1, 0.9);
    colorTransferFunction->AddRGBPoint(196.0, 0.27, 0.21, 0.1);
    colorTransferFunction->AddRGBPoint(255.0, 0.8, 0.8, 0.8);

    vtkCreate(volumeProperty, vtkVolumeProperty);
    volumeProperty->SetColor(colorTransferFunction);
    volumeProperty->SetScalarOpacity(opacityTransferFunction);
    volumeProperty->ShadeOn();
    volumeProperty->SetInterpolationTypeToLinear();
    volumeProperty->SetAmbient(0.2);
    volumeProperty->SetDiffuse(0.9);
    volumeProperty->SetSpecular(0.2);
    volumeProperty->SetSpecularPower(10);

    vtkCreate(compositeFunction, vtkVolumeRayCastCompositeFunction);
    vtkCreate(gradest, vtkFiniteDifferenceGradientEstimator);
    vtkCreate(volumeMapper, vtkVolumeRayCastMapper);
    volumeMapper->SetVolumeRayCastFunction(compositeFunction);
    volumeMapper->SetGradientEstimator(gradest);
    volumeMapper->SetInputConnection(imageCast->GetOutputPort());
    volumeMapper->SetNumberOfThreads(3);

    vtkCreate(plane, vtkPlane);
    vtkCreate(volume, vtkVolume);
    vtkCreate(myCallback, vtkTIPWCallback);
    volume->SetMapper(volumeMapper);
    volume->SetProperty(volumeProperty);
    myCallback->setParameter(plane, volume, volumeMapper);

    vtkCreate(planeWidget, vtkImplicitPlaneWidget);
    planeWidget->SetInteractor(vtkWidget->GetInteractor());
    planeWidget->SetPlaceFactor(1.25);
    planeWidget->SetInputConnection(imageCast->GetOutputPort());
    planeWidget->GetPlaneProperty()->SetColor(0,0,0);
    planeWidget->PlaceWidget();
    planeWidget->AddObserver(vtkCommand::InteractionEvent,myCallback);
    planeWidget->On();

    renderer->AddVolume(volume);
    renderer->SetBackground(0, 0, 0);
    vtkWidget->resize(WINDOW_WIDTH, WINDOW_HEIGHT);
    vtkWidget->show();

    return a.exec();
}
